"use client";
import { Canvas, useFrame, useThree } from "@react-three/fiber";
import * as THREE from "three";
import {
    OrbitControls,
    useGLTF,
    ContactShadows,
    Environment,
} from "@react-three/drei";
import { Suspense, useEffect, useMemo, useRef, useState } from "react";

function HeartModel() {
    const { scene } = useGLTF("/models/heart.glb");
    return <primitive object={scene} scale={1.2} />;
}

const transcriptomeData = [
    { id: "geneA", x: 1.2, y: 0.3, z: -0.8, expression: 3.5 },
    { id: "geneB", x: -0.9, y: 1.1, z: 0.4, expression: 7.2 },
    { id: "geneC", x: 0.5, y: -1.0, z: 0.6, expression: 5.8 },
];

function AIPointCloud({ data, onSelect, selected }) {
    const positions = useMemo(() => {
        const arr = new Float32Array(data.length * 3);
        data.forEach((d, i) => {
            arr[i * 3] = d.x;
            arr[i * 3 + 1] = d.y;
            arr[i * 3 + 2] = d.z;
        });
        return arr;
    }, [data]);

    const colors = useMemo(() => {
        const arr = new Float32Array(data.length * 3);
        const color = new THREE.Color();
        data.forEach((d: any, i: any) => {
            if (d.expression > 6) color.set("#ff6b6b");
            else if (d.expression > 4) color.set("#ffd166");
            else color.set("#4dabf7");
            arr[i * 3] = color.r;
            arr[i * 3 + 1] = color.g;
            arr[i * 3 + 2] = color.b;
        });
        return arr;
    }, [data]);

    const geometry = useMemo(() => {
        const geo = new THREE.BufferGeometry();
        geo.setAttribute("position", new THREE.BufferAttribute(positions, 3));
        geo.setAttribute("color", new THREE.BufferAttribute(colors, 3));
        return geo;
    }, [positions, colors]);

    const material = new THREE.PointsMaterial({
        size: 0.02,
        color: new THREE.Color("#ff4d6d"),
        transparent: true,
        opacity: 0.4,
        blending: THREE.AdditiveBlending,
        depthWrite: false,
        sizeAttenuation: true,
    });

    return (
        <points
            geometry={geometry}
            onPointerDown={(e) => {
                e.stopPropagation();
                const index = e.index;
                if (index !== undefined) onSelect(data[index]);
            }}
        >
            <pointsMaterial
                vertexColors
                size={0.06}
                transparent
                opacity={0.8}
                blending={THREE.AdditiveBlending}
                depthWrite={false}
                sizeAttenuation
            />
        </points>
    );
}

function PotreePointCloud({
    numPoints = 500,
    onSelect,
}: {
    numPoints?: number;
    onSelect: (point: {
        id: string;
        x: number;
        y: number;
        z: number;
        intensity: number;
    }) => void;
}) {
    const groupRef = useRef<THREE.Group>(null);
    const [selectedPoint, setSelectedPoint] = useState<any>(null);
    const { camera, gl } = useThree();

    const pointsData = useMemo(() => {
        const arr = [];
        for (let i = 0; i < numPoints; i++) {
            arr.push({
                id: `Point-${i}`,
                x: (Math.random() - 0.5) * 3,
                y: (Math.random() - 0.5) * 3,
                z: (Math.random() - 0.5) * 3,
                intensity: Math.random(),
            });
        }
        return arr;
    }, [numPoints]);

    useEffect(() => {
        if (!groupRef.current) return;

        // 清空已有的点云
        groupRef.current.clear();

        const geometry = new THREE.BufferGeometry();
        const positions = new Float32Array(pointsData.length * 3);
        const colors = new Float32Array(pointsData.length * 3);

        pointsData.forEach((p, i) => {
            positions[i * 3] = p.x;
            positions[i * 3 + 1] = p.y;
            positions[i * 3 + 2] = p.z;

            const color = new THREE.Color();
            // 根据 intensity 设置颜色渐变
            color.setHSL(0.6 * (1 - p.intensity), 1, 0.5);
            colors[i * 3] = color.r;
            colors[i * 3 + 1] = color.g;
            colors[i * 3 + 2] = color.b;
        });

        geometry.setAttribute(
            "position",
            new THREE.BufferAttribute(positions, 3)
        );
        geometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));

        const material = new THREE.PointsMaterial({
            size: 0.04,
            vertexColors: true,
            transparent: true,
            opacity: 0.8,
            blending: THREE.AdditiveBlending,
            depthWrite: false,
            sizeAttenuation: true,
        });

        const points = new THREE.Points(geometry, material);
        groupRef.current.add(points);

        // 鼠标事件：选中点
        const raycaster = new THREE.Raycaster();
        const mouse = new THREE.Vector2();

        const onMouseClick = (event: MouseEvent) => {
            const canvas = event.target as HTMLCanvasElement;
            const rect = canvas.getBoundingClientRect();
            mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
            mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

            // raycaster.update();
            raycaster.setFromCamera(mouse, camera);

            const intersects = raycaster.intersectObject(points);
            if (intersects.length > 0) {
                const intersectedPoint = intersects[0].point;
                const index = intersects[0].index;

                if (index !== undefined) {
                    const selected = pointsData[index];
                    setSelectedPoint(selected);
                    onSelect(selected);
                }
            }
        };

        window.addEventListener("click", onMouseClick);

        return () => {
            window.removeEventListener("click", onMouseClick);
        };
    }, [pointsData, onSelect]);

    return (
        <>
            <group ref={groupRef} />
        </>
    );
}

export default function HeartScene() {
    const [selected, setSelected] = useState<any>(null);

    const data = useMemo(() => {
        const arr = [];
        for (let i = 0; i < 50; i++) {
            arr.push({
                x: (Math.random() - 0.5) * 2,
                y: (Math.random() - 0.5) * 2,
                z: (Math.random() - 0.5) * 2,
                expression: Math.random() * 8,
                id: i,
            });
        }
        return arr;
    }, []);

    return (
        <div className="relative w-full h-full bg-gradient-radial from-[#2b2b2b] via-[#121212] to-[#000] overflow-hidden">
            <Canvas
                shadows
                camera={{ position: [0, 0, 4], fov: 45 }}
                gl={{ toneMappingExposure: 2 }}
            >
                {/* 背景颜色偏暗 */}
                <color attach="background" args={["transparent"]} />

                {/* 柔和的环境光 */}
                <ambientLight intensity={1} />

                {/* 主方向光：模拟舞台上方打光 */}
                <directionalLight
                    position={[3, 5, 6]}
                    intensity={3}
                    castShadow
                    shadow-mapSize={[2048, 2048]}
                />

                {/* 反射光（模拟地面或环境反射） */}
                <pointLight
                    position={[-3, -2, -5]}
                    intensity={0.45}
                    color="#ffb6b6"
                />

                <Suspense fallback={null}>
                    <group>
                        <HeartModel />
                        {/* <GenePoints onSelect={(d) => setSelected(d)} /> */}
                        {/* <AIPointCloud
                            data={data}
                            onSelect={(d: any) => setSelected(d)}
                            selected={selected}
                        /> */}
                        <PotreePointCloud
                            numPoints={500}
                            onSelect={(d) => setSelected(d)}
                        />
                    </group>

                    {/* 柔和阴影 */}
                    {/* <ContactShadows
                        position={[0, -1.2, 0]}
                        opacity={0.4}
                        scale={8}
                        blur={2.5}
                        far={3}
                    /> */}

                    {/* 模拟反光环境（柔和的立体反光） */}
                    <Environment
                        preset="studio"
                        background={false}
                        environmentIntensity={0.4}
                    />
                </Suspense>

                <OrbitControls enablePan={false} enableZoom={true} />
            </Canvas>

            {/* 外层背景渐变（中心亮，四周黑） */}
            <div
                className="absolute inset-0 pointer-events-none"
                style={{
                    background:
                        "radial-gradient(circle at 50% 40%, rgba(60,60,60,0.7) 0%, rgba(0,0,0,1) 90%)",
                }}
            ></div>

            {/* 信息展示浮窗 */}
            {selected && (
                <div className="absolute top-5 right-5 bg-gray-900 bg-opacity-80 text-white p-4 rounded-lg shadow-lg w-64">
                    <h2 className="font-bold text-lg mb-2">{selected.id}</h2>
                    <p>Expression: {selected.expression}</p>
                    <p>
                        Coord: ({selected.x.toFixed(2)}, {selected.y.toFixed(2)}
                        , {selected.z.toFixed(2)})
                    </p>
                    <button
                        onClick={() => setSelected(null)}
                        className="mt-3 px-3 py-1 bg-red-500 rounded hover:bg-red-400"
                    >
                        Close
                    </button>
                </div>
            )}
        </div>
    );
}
